
#include "trace.h"

int openTraceFile(char * filename)
{
	// Open the file, store it in file variable
	if ((TraceFile = fopen(filename, "r")) == NULL)
	{
		return 1;
	}

	return 0;
}

int getInstruction(instruction* instr, results_s* results)
{
	// Make sure a file has been opened already
	if (TraceFile == NULL)
	{
			return 1;
	}

	char opType;

	// Get operation type and program counter while checking for end of file
	if (fscanf(TraceFile, "%c %8s", &opType,instr->pc) == EOF)
			return -1;
	instr->pc[8] = 0;

	// Need to parse execution info differently for each operation type
	switch (opType)
	{
		case 'L':
			// Parse the address of load
			instr->opType = TO_Load;
			fscanf(TraceFile, "%8s ", instr->exInfo.ldstAddr);
			instr->exInfo.ldstAddr[8] = 0;

			results->numInstr.numLoad++;
			results->numInstr.numTotal++;
			results->instRefs++;
			results->dataRefs++;
			break;
		case 'S':
			// Parse the address of save
			instr->opType = TO_Store;
			fscanf(TraceFile, "%8s ", instr->exInfo.ldstAddr);
			instr->exInfo.ldstAddr[8] = 0;

			results->numInstr.numStore++;
			results->numInstr.numTotal++;
			results->instRefs++;
			results->dataRefs++;
			break;
		case 'B':
			// Parse the 0/1 of whether branch is taken
			instr->opType = TO_Branch;
			fscanf(TraceFile, "%1d ", &(instr->exInfo.brTaken));

			results->numInstr.numBranch++;
			results->numInstr.numTotal++;
			results->instRefs++;
			break;
		case 'C':
			// Parse the number of clock ticks computation takes
			instr->opType = TO_Computation;
			fscanf(TraceFile, "%1d ", &(instr->exInfo.compLatency));

			results->numInstr.numComp++;
			results->numInstr.numTotal++;
			results->instRefs++;
			break;
		default:
			instr->opType = TO_InvalidValue;
			break;
	}

	return 0;
}

/* void printInstruction(instruction* instr)
 * Print an instruction contents to stdout
 */
void printInstruction(instruction* instr)
{
	printf("Instruction:\n");
	switch (instr->opType)
	{
		case (int)TO_Load:
			printf("   optype:TO_Load\n");
			printf("   pc:%8s\n",instr->pc);
			printf("   execinfo:%8s\n",instr->exInfo.ldstAddr);
			break;
		case TO_Store:
			printf("   optype:TO_Store\n");
			printf("   pc:%8s\n",instr->pc);
			printf("   execinfo:%8s\n",instr->exInfo.ldstAddr);
			break;
		case TO_Branch:
			printf("   optype:TO_Branch\n");
			printf("   pc:%8s\n",instr->pc);
			printf("   execinfo:%d\n",instr->exInfo.brTaken);
			break;
		case TO_Computation:
			printf("   optype:TO_Computation\n");
			printf("   pc:%8s\n",instr->pc);
			printf("   execinfo:%d\n",instr->exInfo.compLatency);
			break;
		case TO_InvalidValue:
		default:
			printf("   optype:TO_InvalidValue\n");
			printf("   pc:EMPTY\n");
			printf("   execinfo:EMPTY\n");
			break;
	}
}
